use core::{cell::UnsafeCell, mem::MaybeUninit, ops::Deref};


unsafe impl<T: Send> Send for MutCell<T> {}
unsafe impl<T: Sync> Sync for MutCell<T> {}

#[repr(transparent)]
pub struct MutCell<T>(UnsafeCell<T>);

impl<T> Deref for MutCell<T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        unsafe { &*self.0.get() }
    }
}

impl<T> MutCell<T> {
    pub const fn const_new(value: T) -> Self {
        Self(UnsafeCell::new(value))
    }

    pub const unsafe fn as_mut(&self) -> &mut T {
        &mut *self.0.get()
    }

    pub const fn as_mut_ptr(&self) -> *mut T {
        self.0.get()
    }
}



unsafe impl<T: Send> Send for UninitCell<T> {}
unsafe impl<T: Sync> Sync for UninitCell<T> {}

#[repr(transparent)]
pub struct UninitCell<T>(UnsafeCell<MaybeUninit<T>>);

impl<T> Deref for UninitCell<T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        unsafe { (&*self.0.get()).assume_init_ref() }
    }
}

impl<T> UninitCell<T> {
    pub const fn const_new() -> Self {
        Self(UnsafeCell::new(MaybeUninit::uninit()))
    }

    pub unsafe fn init(&self, value: T) {
        (&mut *self.0.get()).write(value);
    }

    pub unsafe fn drop(&self) {
        (&mut *self.0.get()).assume_init_drop();
    }

    pub unsafe fn as_mut(&self) -> &mut T {
        (&mut *self.0.get()).assume_init_mut()
    }
}





